package utils

import (
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"sync"
	"time"
)

// LogLevel 日志级别
type LogLevel int

const (
	LogLevelInfo LogLevel = iota
	LogLevelWarn
	LogLevelError
)

// Logger 日志管理器
type Logger struct {
	infoLogger  *log.Logger
	warnLogger  *log.Logger
	errorLogger *log.Logger

	infoFile  *os.File
	warnFile  *os.File
	errorFile *os.File

	mutex sync.RWMutex
}

var globalLogger *Logger
var loggerOnce sync.Once

// GetLogger 获取全局日志实例
func GetLogger() *Logger {
	loggerOnce.Do(func() {
		globalLogger = &Logger{}
		globalLogger.init()
	})
	return globalLogger
}

// init 初始化日志管理器
func (l *Logger) init() {
	l.mutex.Lock()
	defer l.mutex.Unlock()

	// 创建logs目录
	logsDir := "logs"
	if err := os.MkdirAll(logsDir, 0755); err != nil {
		log.Printf("创建logs目录失败: %v", err)
		return
	}

	// 获取当前日期作为文件名后缀
	dateStr := time.Now().Format("2006-01-02")

	// 创建日志文件
	infoPath := filepath.Join(logsDir, fmt.Sprintf("info-%s.log", dateStr))
	warnPath := filepath.Join(logsDir, fmt.Sprintf("warn-%s.log", dateStr))
	errorPath := filepath.Join(logsDir, fmt.Sprintf("error-%s.log", dateStr))

	// 打开日志文件
	var err error
	l.infoFile, err = os.OpenFile(infoPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		log.Printf("打开info日志文件失败: %v", err)
		return
	}

	l.warnFile, err = os.OpenFile(warnPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		log.Printf("打开warn日志文件失败: %v", err)
		return
	}

	l.errorFile, err = os.OpenFile(errorPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		log.Printf("打开error日志文件失败: %v", err)
		return
	}

	// 创建日志记录器
	l.infoLogger = log.New(
		io.MultiWriter(l.infoFile, os.Stdout),
		"[INFO] ",
		log.Ldate|log.Ltime|log.Lshortfile,
	)

	l.warnLogger = log.New(
		io.MultiWriter(l.warnFile, os.Stdout),
		"[WARN] ",
		log.Ldate|log.Ltime|log.Lshortfile,
	)

	l.errorLogger = log.New(
		io.MultiWriter(l.errorFile, os.Stderr),
		"[ERROR] ",
		log.Ldate|log.Ltime|log.Lshortfile,
	)
}

// Info 记录信息级别日志
func (l *Logger) Info(format string, args ...interface{}) {
	l.mutex.RLock()
	defer l.mutex.RUnlock()

	if l.infoLogger != nil {
		l.infoLogger.Printf(format, args...)
	}
}

// Warn 记录警告级别日志
func (l *Logger) Warn(format string, args ...interface{}) {
	l.mutex.RLock()
	defer l.mutex.RUnlock()

	if l.warnLogger != nil {
		l.warnLogger.Printf(format, args...)
	}
}

// Error 记录错误级别日志
func (l *Logger) Error(format string, args ...interface{}) {
	l.mutex.RLock()
	defer l.mutex.RUnlock()

	if l.errorLogger != nil {
		l.errorLogger.Printf(format, args...)
	}
}

// InfoLn 记录信息级别日志（换行）
func (l *Logger) InfoLn(args ...interface{}) {
	l.mutex.RLock()
	defer l.mutex.RUnlock()

	if l.infoLogger != nil {
		l.infoLogger.Println(args...)
	}
}

// WarnLn 记录警告级别日志（换行）
func (l *Logger) WarnLn(args ...interface{}) {
	l.mutex.RLock()
	defer l.mutex.RUnlock()

	if l.warnLogger != nil {
		l.warnLogger.Println(args...)
	}
}

// ErrorLn 记录错误级别日志（换行）
func (l *Logger) ErrorLn(args ...interface{}) {
	l.mutex.RLock()
	defer l.mutex.RUnlock()

	if l.errorLogger != nil {
		l.errorLogger.Println(args...)
	}
}

// Close 关闭日志文件
func (l *Logger) Close() {
	l.mutex.Lock()
	defer l.mutex.Unlock()

	if l.infoFile != nil {
		l.infoFile.Close()
	}
	if l.warnFile != nil {
		l.warnFile.Close()
	}
	if l.errorFile != nil {
		l.errorFile.Close()
	}
}

// RotateLogFiles 轮转日志文件（每天一个文件）
func (l *Logger) RotateLogFiles() {
	l.mutex.Lock()
	defer l.mutex.Unlock()

	// 关闭现有文件
	if l.infoFile != nil {
		l.infoFile.Close()
	}
	if l.warnFile != nil {
		l.warnFile.Close()
	}
	if l.errorFile != nil {
		l.errorFile.Close()
	}

	// 重新初始化（会创建新的日期文件）
	l.init()
}

// 便捷函数
func LogInfo(format string, args ...interface{}) {
	GetLogger().Info(format, args...)
}

func LogWarn(format string, args ...interface{}) {
	GetLogger().Warn(format, args...)
}

func LogError(format string, args ...interface{}) {
	GetLogger().Error(format, args...)
}

func LogInfoLn(args ...interface{}) {
	GetLogger().InfoLn(args...)
}

func LogWarnLn(args ...interface{}) {
	GetLogger().WarnLn(args...)
}

func LogErrorLn(args ...interface{}) {
	GetLogger().ErrorLn(args...)
}
